import errno
import sys
import os
import time
import importlib as IM
from collections import OrderedDict

from pyneuroml import pynml

import c302
from c302 import c302_utils

save_fig_dir = "summary/"
save_image_dir = "images"
save_image_full_dir = "%s/%s" % (save_fig_dir, save_image_dir)


def run_c302(
    config,
    parameter_set,
    prefix,
    duration,
    dt,
    simulator,
    save=False,
    show_plot_already=True,
    data_reader="SpreadsheetDataReader",
    verbose=False,
    plot_ca=True,
    plot_connectivity=False,
    param_overrides={},
    config_param_overrides={},
    config_package="",
    target_directory="examples",
    save_fig_to=None,
):
    if save_fig_to:
        global save_fig_dir
        save_fig_dir = save_fig_to

    c302.print_(
        "********************\n\n   Going to generate c302_%s_%s and run for %sms (dt: %sms) on %s\n\n********************"
        % (parameter_set, config, duration, dt, simulator)
    )

    if not config_package:
        config_package = "c302"

    setup = IM.import_module("%s.c302_%s" % (config_package, config)).setup

    try:
        os.makedirs(target_directory)
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise

    cells, cells_to_stimulate, params, muscles, nml_doc = setup(
        parameter_set,
        data_reader=data_reader,
        generate=True,
        duration=duration,
        dt=dt,
        target_directory=target_directory,
        verbose=verbose,
        param_overrides=param_overrides,
        config_param_overrides=config_param_overrides,
    )

    orig_dir = os.getcwd()

    os.chdir(target_directory)

    try:
        os.makedirs(save_fig_dir)
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise

    lems_file = "LEMS_c302_%s_%s.xml" % (parameter_set, config)

    if simulator == "jNeuroML":
        results = pynml.run_lems_with_jneuroml(
            lems_file, nogui=True, load_saved_data=True, verbose=verbose
        )
    elif simulator == "jNeuroML_NEURON":
        results = pynml.run_lems_with_jneuroml_neuron(
            lems_file, nogui=True, load_saved_data=True, verbose=verbose
        )

    c302.print_("Finished simulation of %s and have reloaded results" % lems_file)

    c302_utils.plot_c302_results(
        results,
        config,
        parameter_set,
        directory=save_image_full_dir,
        save=save,
        show_plot_already=show_plot_already,
        data_reader=data_reader,
        plot_ca=plot_ca,
    )

    if plot_connectivity:
        c302_utils.generate_conn_matrix(nml_doc, save_fig_dir=save_image_full_dir)

    os.chdir(orig_dir)

    return cells, cells_to_stimulate, params, muscles


if __name__ == "__main__":
    if "-full" in sys.argv:
        run_c302("Full", "C", "", 300, 0.05, "jNeuroML_NEURON")

    elif "-fullA" in sys.argv:
        run_c302("Full", "A", "", 1000, 0.05, "jNeuroML_NEURON")

    elif "-fullB" in sys.argv:
        run_c302("Full", "B", "", 1000, 0.05, "jNeuroML_NEURON")

    elif "-fullC0" in sys.argv:
        run_c302("Full", "C0", "", 1000, 0.05, "jNeuroML_NEURON")

    elif "-fullC" in sys.argv:
        run_c302("Full", "C", "", 1000, 0.05, "jNeuroML_NEURON")

    elif "-fullC1" in sys.argv:
        run_c302("Full", "C1", "", 1000, 0.05, "jNeuroML_NEURON")

    elif "-fullD" in sys.argv:
        run_c302("Full", "D", "", 1000, 0.05, "jNeuroML_NEURON")

    elif "-fullD1" in sys.argv:
        run_c302("Full", "D1", "", 1000, 0.05, "jNeuroML_NEURON")

    elif "-fw" in sys.argv:
        run_c302(
            "AVB_FW",
            "C2",
            "",
            4000,
            0.05,
            "jNeuroML_NEURON",
            config_package="notebooks.configs.AVB",
            data_reader="UpdatedSpreadsheetDataReader2",
        )

    elif "-fw1" in sys.argv:
        # run_c302('FW','C2','',1000,0.05,'jNeuroML_NEURON', data_reader='UpdatedSpreadsheetDataReader2', save=True)
        run_c302(
            "FW",
            "C2",
            "",
            5000,
            0.005,
            "jNeuroML_NEURON",
            data_reader="UpdatedSpreadsheetDataReader2",
            save=True,
            show_plot_already=False,
        )

    elif "-fwTest" in sys.argv:
        run_c302(
            "FW",
            "C2",
            "",
            5000,
            0.05,
            "jNeuroML_NEURON",
            data_reader="UpdatedSpreadsheetDataReader2",
            save=True,
            show_plot_already=True,
        )

    elif "-fullC2" in sys.argv:
        run_c302("Full", "C2", "", 1000, 0.05, "jNeuroML_NEURON")

    elif "-muscle1" in sys.argv:
        run_c302(
            "MuscleTest",
            "C2",
            "",
            2000,
            0.05,
            "jNeuroML_NEURON",
            data_reader="UpdatedSpreadsheetDataReader",
            save=True,
        )

    elif "-head1" in sys.argv:
        run_c302(
            "HeadMuscleTest",
            "C2",
            "",
            4000,
            0.05,
            "jNeuroML_NEURON",
            config_package="notebooks.configs.Head",
            data_reader="UpdatedSpreadsheetDataReader",
        )

    elif "-muscle" in sys.argv or "-muscles" in sys.argv:
        run_c302("Muscles", "C", "", 500, 0.05, "jNeuroML_NEURON")

    elif "-musclesA" in sys.argv or "-muscA" in sys.argv:
        run_c302("Muscles", "A", "", 1000, 0.05, "jNeuroML_NEURON")

    elif "-musclesB" in sys.argv or "-muscB" in sys.argv:
        run_c302("Muscles", "B", "", 1000, 0.05, "jNeuroML_NEURON")

    elif "-musclesC0" in sys.argv or "-muscC0" in sys.argv:
        run_c302("Muscles", "C0", "", 1000, 0.05, "jNeuroML_NEURON")

    elif "-musclesC" in sys.argv or "-muscC" in sys.argv:
        run_c302("Muscles", "C", "", 2000, 0.05, "jNeuroML_NEURON")

    elif "-musclesC1" in sys.argv or "-muscC1" in sys.argv:
        run_c302("Muscles", "C1", "", 2000, 0.05, "jNeuroML_NEURON")

    elif "-musclesD" in sys.argv or "-muscD" in sys.argv:
        run_c302("Muscles", "D", "", 2000, 0.05, "jNeuroML_NEURON")

    elif "-musclesD1" in sys.argv or "-muscD1" in sys.argv:
        run_c302("Muscles", "D1", "", 2000, 0.05, "jNeuroML_NEURON")

    elif "-pharA" in sys.argv or "-pharyngealA" in sys.argv:
        run_c302("Pharyngeal", "A", "", 500, 0.01, "jNeuroML_NEURON")

    elif "-pharB" in sys.argv or "-pharyngealB" in sys.argv:
        run_c302("Pharyngeal", "B", "", 500, 0.01, "jNeuroML_NEURON")

    elif "-pharC0" in sys.argv or "-pharyngealC0" in sys.argv:
        run_c302("Pharyngeal", "C0", "", 500, 0.01, "jNeuroML_NEURON")

    elif "-pharC1" in sys.argv or "-pharyngealC1" in sys.argv:
        run_c302("Pharyngeal", "C1", "", 500, 0.01, "jNeuroML_NEURON")

    elif "-pharD" in sys.argv or "-pharyngealD" in sys.argv:
        run_c302("Pharyngeal", "D", "", 500, 0.05, "jNeuroML_NEURON")

    elif "-pharD1" in sys.argv or "-pharyngealD1" in sys.argv:
        run_c302("Pharyngeal", "D1", "", 500, 0.05, "jNeuroML_NEURON")

    elif "-phar" in sys.argv or "-pharyngeal" in sys.argv:
        run_c302("Pharyngeal", "C", "", 500, 0.01, "jNeuroML_NEURON")

    elif "-synsA" in sys.argv:
        run_c302("Syns", "A", "", 500, 0.05, "jNeuroML_NEURON")

    elif "-synsB" in sys.argv:
        run_c302("Syns", "B", "", 500, 0.05, "jNeuroML_NEURON")

    elif "-synsC0" in sys.argv:
        run_c302("Syns", "C0", "", 500, 0.05, "jNeuroML_NEURON")

    elif "-synsC" in sys.argv:
        run_c302("Syns", "C", "", 500, 0.05, "jNeuroML_NEURON")

    elif "-synsC1" in sys.argv:
        run_c302("Syns", "C1", "", 500, 0.05, "jNeuroML_NEURON")

    elif "-synsD" in sys.argv:
        run_c302("Syns", "D", "", 500, 0.05, "jNeuroML_NEURON")

    elif "-synsD1" in sys.argv:
        run_c302("Syns", "D1", "", 500, 0.05, "jNeuroML_NEURON")

    elif "-socialA" in sys.argv:
        run_c302("Social", "A", "", 2500, 0.05, "jNeuroML_NEURON")

    elif "-socialB" in sys.argv:
        run_c302("Social", "B", "", 2500, 0.05, "jNeuroML_NEURON")

    elif "-socialC0" in sys.argv:
        run_c302("Social", "C0", "", 2500, 0.05, "jNeuroML_NEURON")

    elif "-socialC" in sys.argv:
        run_c302("Social", "C", "", 2500, 0.05, "jNeuroML_NEURON")

    elif "-socialC1" in sys.argv:
        run_c302("Social", "C1", "", 2500, 0.05, "jNeuroML_NEURON")

    elif "-oscA" in sys.argv:
        run_c302("Oscillator", "A", "", 600, 0.05, "jNeuroML_NEURON")

    elif "-oscB" in sys.argv:
        run_c302("Oscillator", "B", "", 600, 0.05, "jNeuroML_NEURON")

    elif "-oscC0" in sys.argv:
        run_c302("Oscillator", "C0", "", 2000, 0.025, "jNeuroML_NEURON")

    elif "-oscmC0" in sys.argv:
        run_c302("OscillatorM", "C0", "", 2000, 0.025, "jNeuroML_NEURON")

    elif "-test" in sys.argv:
        run_c302(
            "Oscillator", "C0", "", 2000, 0.025, "jNeuroML", show_plot_already=False
        )

    elif "-oscC" in sys.argv:
        run_c302("Oscillator", "C", "", 2000, 0.05, "jNeuroML_NEURON")

    elif "-oscC1" in sys.argv:
        run_c302("Oscillator", "C1", "", 2000, 0.05, "jNeuroML_NEURON")

    elif "-KatoC1" in sys.argv:
        run_c302("Kato", "C1", "", 1080, 0.05, "jNeuroML_NEURON")

    elif "-targetC0" in sys.argv:
        run_c302("TargetMuscle", "C0", "", 300, 0.05, "jNeuroML")

    elif "-twC2" in sys.argv:
        run_c302(
            "TapWithdrawal",
            "C2",
            "",
            500,
            0.05,
            "jNeuroML_NEURON",
            data_reader="UpdatedSpreadsheetDataReader",
        )

    elif "-sinusC2" in sys.argv:
        run_c302(
            "SinusoidalInputTest",
            "C2",
            "",
            1000,
            0.05,
            "jNeuroML_NEURON",
            data_reader="UpdatedSpreadsheetDataReader",
        )

    elif "-iA" in sys.argv:
        run_c302("IClamp", "A", "", 6000, 0.05, "jNeuroML")
    elif "-iB" in sys.argv:
        run_c302("IClamp", "B", "", 6000, 0.05, "jNeuroML")
    elif "-iC0" in sys.argv:
        run_c302("IClamp", "C0", "", 6000, 0.05, "jNeuroML")
    elif "-iC" in sys.argv:
        run_c302("IClamp", "C", "", 6000, 0.05, "jNeuroML")
    elif "-iC1" in sys.argv:
        run_c302("IClamp", "C1", "", 6000, 0.05, "jNeuroML", save=True)
    elif "-iD" in sys.argv:
        run_c302("IClamp", "D", "", 6000, 0.05, "jNeuroML_NEURON", save=True)
    elif "-iD1" in sys.argv:
        run_c302("IClamp", "D1", "", 6000, 0.05, "jNeuroML_NEURON", save=True)

    elif "-all" in sys.argv:
        print("Generating all plots")
        html = "<table>\n"

        levels = ["A", "B", "C0", "C", "C1", "C2", "D", "D1"]
        # levels = ['D','D1']
        # levels = ['C2']
        # levels = ['C0']

        durations = OrderedDict(
            [
                ("IClamp", 6000),
                ("Syns", 500),
                ("Pharyngeal", 500),
                ("Social", 2500),
                ("Oscillator", 1000),
                ("Muscles", 1000),
                ("Full", 1000),
            ]
        )

        """durations = OrderedDict([('IClamp',1000),
                                ('Syns',500),
                                ('Oscillator',1000),
                                ('OscillatorM',1000)])

        durations = OrderedDict([('IClamp',1000),
                                ('Syns',500),
                                ('Social',2500)])"""

        html += "<tr>\n"
        html += "  <td>&nbsp;</td>\n"
        for p in durations.keys():
            html += (
                '  <td align="center"><b><a href="https://github.com/openworm/c302/blob/master/c302/c302_%s.py">%s</a></b></td>\n'
                % (p, p)
            )

        html += "</tr>\n"
        for c in levels:
            print("Generating for: %s" % c)

            img_loc = save_image_dir

            html += "\n<tr>\n"
            html += (
                '  <td><b><a href="https://github.com/openworm/c302/blob/master/c302/parameters_%s.py">Params %s</a></b></td>\n'
                % (c, c)
            )
            for p in durations.keys():
                print("Params: %s" % p)
                html2 = "<h2>c302 simulation</h2>\n"
                html2 += (
                    "<p>Parameter set: <b>%s</b>; configuration: <b>%s</b></p>\n"
                    % (c, p)
                )
                html2 += "<p>Generated on: %s with c302 v%s</p><br/>\n" % (
                    time.strftime("%a, %d %b %Y", time.gmtime()),
                    c302.__version__,
                )
                html2 += "<table>\n"
                html += '  <td><a href="summary_%s_%s.html">\n' % (c, p)
                html += (
                    '    <img alt="?" src="%s/neurons_%s_%s.png" height="80"/></a>\n'
                    % (img_loc, c, p)
                )

                html += (
                    '    <br/><a href="https://github.com/openworm/c302/blob/master/examples/c302_%s_%s.net.nml">NML</a>\n'
                    % (c, p)
                )
                html += (
                    '    &nbsp;<a href="http://opensourcebrain.org/projects/celegans?explorer=https://raw.githubusercontent.com/openworm/c302/master/examples/c302_%s_%s.net.nml">OSB</a>\n'
                    % (c, p)
                )

                pres = ["neurons_", "neuron_activity_", "muscles_", "muscle_activity_"]
                for pre in pres:
                    html2 += (
                        '\n<tr>\n  <td><a href="%s/%s%s_%s.png"><img alt=" " src="%s/%s%s_%s.png" height="320"/></a></td>\n'
                        % (img_loc, pre, c, p, img_loc, pre, c, p)
                    )
                    if pre == "neurons_":
                        pre = "neuron_"
                    if pre == "muscle_activity_":
                        pre = "muscles_activity_"
                    html2 += (
                        '  <td><a href="%s/traces_%s%s_%s.png"><img alt=" " src="%s/traces_%s%s_%s.png" height="320"/></a></td>\n</tr>\n'
                        % (img_loc, pre, p, c, img_loc, pre, p, c)
                    )

                html2 += "</table>\n"
                html2 += "<table>\n"

                html2 += (
                    '\n<tr><td><a href="%s/c302_%s_%s_exc_to_neurons.png"><img alt=" " src="%s/c302_%s_%s_exc_to_neurons.png" height="320"/></a></td>\n'
                    % (img_loc, c, p, img_loc, c, p)
                )
                html2 += (
                    '\n  <td><a href="%s/c302_%s_%s_inh_to_neurons.png"><img alt=" " src="%s/c302_%s_%s_inh_to_neurons.png" height="320"/></a></td>\n'
                    % (img_loc, c, p, img_loc, c, p)
                )
                html2 += (
                    '\n  <td><a href="%s/c302_%s_%s_elec_neurons_neurons.png"><img alt=" " src="%s/c302_%s_%s_elec_neurons_neurons.png" height="320"/></a></td></tr>\n'
                    % (img_loc, c, p, img_loc, c, p)
                )

                html2 += (
                    '\n<tr><td><a href="%s/c302_%s_%s_exc_to_muscles.png"><img alt=" " src="%s/c302_%s_%s_exc_to_muscles.png" height="320"/></a></td>\n'
                    % (img_loc, c, p, img_loc, c, p)
                )
                html2 += (
                    '\n  <td><a href="%s/c302_%s_%s_inh_to_muscles.png"><img alt=" " src="%s/c302_%s_%s_inh_to_muscles.png" height="320"/></a></td>'
                    % (img_loc, c, p, img_loc, c, p)
                )
                if os.path.isfile(
                    "%s/%s/%s/c302_%s_%s_elec_neurons_muscles.png"
                    % ("examples", save_fig_dir, img_loc, c, p)
                ):
                    html2 += (
                        '\n\n  <td><a href="%s/c302_%s_%s_elec_neurons_muscles.png"><img alt=" " src="%s/c302_%s_%s_elec_neurons_muscles.png" height="320"/></a></td>'
                        % (img_loc, c, p, img_loc, c, p)
                    )
                html2 += "</tr>\n"

                if os.path.isfile(
                    "%s/%s/%s/c302_%s_%s_elec_muscles_muscles.png"
                    % ("examples", save_fig_dir, img_loc, c, p)
                ):
                    html2 += (
                        '\n<tr><td><a href="%s/c302_%s_%s_elec_muscles_muscles.png"><img alt=" " src="%s/c302_%s_%s_elec_muscles_muscles.png" height="320"/></a></td></tr>\n'
                        % (img_loc, c, p, img_loc, c, p)
                    )

                html2 += "</table>\n"

                with open(
                    "examples/%s/summary_%s_%s.html" % (save_fig_dir, c, p), "w"
                ) as f2:
                    f2.write("<html><body>%s</body></html>" % html2)
                with open(
                    "examples/%s/summary_%s_%s.md" % (save_fig_dir, c, p), "w"
                ) as f3:
                    f3.write("### Parameter config summary \n%s" % html2)

                dt = 0.05 if p != "Pharyngeal" else 0.01

                run_c302(
                    p,
                    c,
                    "",
                    durations[p],
                    dt,
                    "jNeuroML_NEURON",
                    save=True,
                    show_plot_already=False,
                    plot_connectivity=True,
                    data_reader="SpreadsheetDataReader",
                )

                html += "  </td>\n"

            html += "</tr>\n"

        html += "</table>\n"

        with open("examples/" + save_fig_dir + "info.html", "w") as f:
            f.write("<html><body>\n%s\n</body></html>" % html)
        with open("examples/" + save_fig_dir + "README.md", "w") as f2:
            f2.write("### c302 activity summary \n%s" % (html.replace(".html", ".md")))

    else:
        run_c302("Syns", "C", "", 500, 0.05, "jNeuroML")
